#include "product.h"
#include "state.h"
#include "event_filters.h"

#include <QGridLayout>
#include <QLabel>
#include <QLineEdit>
#include <QDoubleSpinBox>
#include <QToolTip>
#include <QFile>

ProductView::ProductView( ProductType aType, const State & state, QWidget * parent )
    : QWidget( parent )
    , type( aType ) {
    setObjectName( QString::fromStdString( state.getType( type ).name ) );

    QGridLayout * grid = new QGridLayout{ this };

    // name
    QWidget * label = new QWidget{ this };
    QHBoxLayout * labelLayout = new QHBoxLayout{ label };
    QFont font{};
    font.setPointSize( 18 );
    font.setBold( true );
    if ( QFile::exists( ":/product/" + objectName() ) )
    {
        QLabel * productIcon = new QLabel{ label };
        productIcon->setPixmap( QPixmap{ ":/product/" + objectName() }.scaledToHeight( 32, Qt::SmoothTransformation ) );
        labelLayout->addWidget( productIcon );
    }
    QLabel * text = new QLabel{ objectName(), label };
    labelLayout->addWidget( text );
    text->setFont( font );

    // weight
    weight = new QDoubleSpinBox{ this };
    weight->setToolTip( objectName() + " weight" );
    weight->setMaximum( 99 );
    weight->setMinimum( 1E-5 );
    weight->setDecimals( 4 );
    weight->setSingleStep( 0.01 );
    connect( weight, QOverload<double>::of( &QDoubleSpinBox::valueChanged ), this, [this]( double w ) { emit weightChanged( type, w ); } );

    // factor
    factor = new QDoubleSpinBox{ this };
    factor->setToolTip( objectName() + " factor" );
    factor->setMaximum( 9.99 );
    factor->setMinimum( 1E-5 );
    factor->setDecimals( 4 );
    factor->setSingleStep( 0.01 );
    connect( factor, QOverload<double>::of( &QDoubleSpinBox::valueChanged ), this, [this]( double f ) { emit factorChanged( type, f ); } );

    // value
    value = new QLineEdit{ this };
    QDoubleValidator * validator = new QDoubleValidator{ 0, 1e25, 3, value };
    value->setValidator( validator );
    value->setAlignment( Qt::AlignCenter );
    value->setToolTip( "Total " + objectName() );
    value->installEventFilter( new ConvertFromLocaleNumber{ this } );
    value->installEventFilter( new SelectAllOnFocusIn{ this } );
    // emit signal only on new correct value and remove focus on return
    connect( value, &QLineEdit::editingFinished, this, [this]() {
        emit valueChanged( type, value->locale().toDouble( value->text() ) );
        value->setText( QString( "%L1" ).arg( value->locale().toDouble( value->text() ), 0, 'f', 0 ) );
    } );
    connect( value, &QLineEdit::textEdited, this, &ProductView::checkText );
    connect( value, &QLineEdit::returnPressed, value, &QLineEdit::clearFocus );

    // production
    production = new QLabel{ this };
    production->setToolTip( objectName() + " production" );

    // layout
    grid->addWidget( label, 0, 0, 1, -1, Qt::AlignCenter );
    grid->addWidget( factor, 1, 0 );
    grid->addWidget( weight, 1, 1 );
    grid->addWidget( value, 2, 0, 1, -1, Qt::AlignCenter );
    grid->addWidget( production, 3, 0, 1, -1, Qt::AlignTop | Qt::AlignJustify );
    updateData( state );
}

void ProductView::updateData( const State & state ) {
    weight->setEnabled( !state.getAutoControl() );
    weight->setValue( state.getType( type ).weight );
    factor->setEnabled( !state.getAutoControl() );
    factor->setValue( state.getType( type ).factor );
    production->setText( "+" + QString( "%L1" ).arg( state.getTotalProductionType( type ), 0, 'f', 0 ) + " / minute" );
    if ( !value->hasFocus() )
    {
        value->setText( QString( "%L1" ).arg( state.getType( type ).value, 0, 'f', 0 ) );
    }
}

void ProductView::checkText() {
    if ( value->hasAcceptableInput() )
    {
        if ( QToolTip::isVisible() )
        {
            QToolTip::hideText();
        }
        value->setStyleSheet( "" );
    } else
    {
        QToolTip::showText( value->mapToGlobal( QPoint{ 0, value->height() } ), "Enter valid number, please!" );
        value->setStyleSheet( "QLineEdit {  background-color: rgba(246, 90, 90, 0.2); }" );
    }
}
